package xiaojian.toolkit.netty.handler.codec.http.transformer;

import com.alibaba.fastjson.JSON;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpHeaders;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import xiaojian.toolkit.bean.tlv.decode.TLVDecoderOfBean;
import xiaojian.toolkit.netty.util.NettyConstants;
import xiaojian.toolkit.util.ByteUtils;

public class MixedTransformer implements HttpRequestTransformer {

	private static final Logger logger = LoggerFactory
			.getLogger(MixedTransformer.class);

	private TLVDecoderOfBean tlvDecoder;
	private Class<?> targetType;
	private String defaultContentType = NettyConstants.TLV_TYPE;
	private int dumpBytes = 1024;

	public Object transform(FullHttpRequest request) {

		int contentLength = 0;

		try {
			String value = request.headers().get(
					HttpHeaders.Names.CONTENT_LENGTH);
			contentLength = Integer.parseInt(value);
		} catch (Exception e) {
			logger.error("transform", e);
		}

		if (contentLength > 0) {
			byte[] bytes = new byte[contentLength];
			request.content().readBytes(bytes);

			if (logger.isTraceEnabled()) {
				logger.trace("decode TLV's raw bytes -->");
				logger.trace(ByteUtils.bytesAsTLVHexString(bytes, dumpBytes));
			}

			String contentType = request.headers().get(
					HttpHeaders.Names.CONTENT_TYPE);
			if (contentType == null) {
				contentType = defaultContentType;
				request.headers().set(HttpHeaders.Names.CONTENT_TYPE,
						contentType);
			}
			Object bean = null;
			if (NettyConstants.TLV_TYPE.equalsIgnoreCase(contentType)) {
				bean = tlvDecoder.decode(contentLength, bytes,
						tlvDecoder.getDecodeContextFactory()
								.createDecodeContext(targetType, null));
			} else if (NettyConstants.JSON_TYPE.equalsIgnoreCase(contentType)) {
				bean = JSON.parseObject(bytes, targetType);
			} else {
				throw new HttpTransformException(UNKNOWN_CONTENT_TYPE_CODE,
						UNKNOWN_CONTENT_TYPE_DESC + ":" + contentType);
			}

			return bean;
		}

		return null;
	}

	/**
	 * @return the dumpBytes
	 */
	public int getDumpBytes() {
		return dumpBytes;
	}

	/**
	 * @param dumpBytes
	 *            the dumpBytes to set
	 */
	public void setDumpBytes(int dumpBytes) {
		this.dumpBytes = dumpBytes;
	}

	public String getDefaultContentType() {
		return defaultContentType;
	}

	public void setDefaultContentType(String defaultContentType) {
		this.defaultContentType = defaultContentType;
	}

	public Class<?> getTargetType() {
		return targetType;
	}

	public void setTargetType(Class<?> targetType) {
		this.targetType = targetType;
	}

	public TLVDecoderOfBean getTlvDecoder() {
		return tlvDecoder;
	}

	public void setTlvDecoder(TLVDecoderOfBean tlvDecoder) {
		this.tlvDecoder = tlvDecoder;
	}
}
